SIGACTION(2) | Linux Programmer's Manual | SIGACTION(2) |
名前¶
sigaction - シグナルの動作の確認と変更
書式¶
#include <signal.h> int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
glibc
向けの機能検査マクロの要件
(feature_test_macros(7) 参照):
sigaction(): _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE
説明¶
sigaction() システムコールは、特定のシグナルを受信した際の プロセスの動作を変更するのに使用される (シグナルの概要については signal(7) を参照)。
signum には、 SIGKILL と SIGSTOP 以外の有効なシグナルをどれでも指定できる。
act が NULL 以外であれば、シグナル signum の新しい動作 (action) として act が設定される。 oldact が NULL でなければ、今までの動作が oldact に格納される。
sigaction 構造体は以下のような感じに定義される。
struct sigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void); };
アーキテクチャによっては共用体 (union) が用いられており、その場合には sa_handler と sa_sigaction の両方を同時に割り当てることはできない。
sa_restorer 要素は廃止予定であり使用すべきではない。 POSIX には sa_restorer 要素に関する規定はない。
sa_handler は signum に対応する動作を指定するもので、 デフォルトの動作を行う SIG_DFL、 そのシグナルを無視する SIG_IGN、 シグナルハンドラ関数へのポインタが設定できる。 シグナルハンドラ関数の引き数は一つであり、シグナル番号が引き数として 渡される。
sa_flags に SA_SIGINFO が指定された場合、 (sa_handler ではなく) sa_sigaction により signum に対応するシグナルハンドル関数が指定される。 指定される関数は、最初の引き数としてシグナル番号を、 二番目の引き数として siginfo_t へのポインタを、三番目の引き数として (void * にキャストした) ucontext_t へのポインタを受けとる。
sa_mask は、シグナル・ハンドラ実行中に禁止 (block) すべきシグナルのマスクを指定する (ハンドラ実行中のシグナルの禁止は、シグナル・ハンドラが起動されたスレッド のシグナルのマスクに追加することで行われる)。 さらに、 SA_NODEFER フラグが指定されていない場合は、ハンドラを起動するきっかけとなる シグナルにも sa_mask が適用される。
sa_flags はシグナル・ハンドラの動作を変更するためのフラグの集合を指定する。 sa_flags には、以下に示すフラグの (0 個以上の) 論理和をとったものを指定する。
- SA_NOCLDSTOP
- signum が SIGCHLD の場合、 子プロセスが停止したり (子プロセスが SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU を受けたとき) 再開したり (子プロセスが SIGCONT を受けたとき) したときに SIGCHLD の通知を受けない。 このフラグは、 SIGCHLD に対してハンドラを設定する際にのみ意味を持つ。
- SA_NOCLDWAIT (Linux 2.6 以降)
- (Linux 2.6 以降) signum が SIGCHLD
の場合、子プロセスが終了したときに
子プロセスをゾンビプロセスに変化させない
(waitpid(2) も参照)。
このフラグは、 SIGCHLD
に対してハンドラを設定する際、もしくはそのシグナルの処理方法を
SIG_DFL
に設定する際にのみ意味を持つ。
SIGCHLD に対してハンドラを設定する際に SA_NOCLDWAIT フラグをセットした場合、 子プロセスが終了した際に SIGCHLD シグナルが生成されるかどうかは、 POSIX.1 では規定されていない。 Linux では、この状況で SIGCHLD シグナルは生成される。 いくつかの他の実装では生成されない。
- SA_NODEFER
- それ自身のシグナル・ハンドラーの内部にいる時でも そのシグナルをマスクしないようにする。 このフラグはシグナルハンドラを設定する際にのみ意味を持つ。 SA_NOMASK はこのフラグと同じ意味だが、廃止されており、非標準である。
- SA_ONSTACK
- sigaltstack(2) で提供される別のシグナル・スタックでシグナルハンドラを呼び出す。 別のシグナル・スタックが利用可能でなければ、デフォルトのスタックが 使用される。 このフラグはシグナルハンドラを設定する際にのみ意味を持つ。
- SA_RESETHAND
- シグナルハンドラが呼ばれる度に、シグナルの動作をデフォルトに戻す。 このフラグはシグナルハンドラを設定する際にのみ意味を持つ。 SA_ONESHOT はこのフラグと同じ意味だが、廃止されており、非標準である。
- SA_RESTART
- いくつかのシステムコールをシグナルの通知の前後で再開できるようにして、 BSD シグナル方式 (semantics) と互換性のある動作を提供する。 このフラグはシグナルハンドラを設定する際にのみ意味を持つ。 signal(7) に書かれているシステムコールの再開に関する議論を参照のこと。
- SA_SIGINFO (Linux 2.2 以降)
- シグナルハンドラは一つではなく、三つの引き数を持つ。この場合は sa_handler のかわりに sa_sigaction を設定しなければならない このフラグはシグナルハンドラを設定する際にのみ意味を持つ。
sa_sigaction のパラメータ siginfo_t は以下の要素を持つ構造体である:
siginfo_t {
int si_signo; /* Signal number */
int si_errno; /* An errno value */
int si_code; /* Signal code */
int si_trapno; /* Trap number that caused
hardware-generated signal
(unused on most architectures) */
pid_t si_pid; /* Sending process ID */
uid_t si_uid; /* Real user ID of sending process */
int si_status; /* Exit value or signal */
clock_t si_utime; /* User time consumed */
clock_t si_stime; /* System time consumed */
sigval_t si_value; /* Signal value */
int si_int; /* POSIX.1b signal */
void *si_ptr; /* POSIX.1b signal */
int si_overrun; /* Timer overrun count; POSIX.1b timers */
int si_timerid; /* Timer ID; POSIX.1b timers */
void *si_addr; /* Memory location which caused fault */
int si_band; /* Band event */
int si_fd; /* File descriptor */ }
si_signo, si_errno, si_code は全てのシグナルに対して定義されている (si_errno は Linux では一般的には使用されない)。 構造体の残りの部分は、共用体 (union) になっているかもしれない。 その場合は該当するシグナルにおいて意味のあるフィールドのみを読み込む ことができる。
- POSIX.1b シグナルと SIGCHLD は si_pid と si_uid を設定する。
- POSIX.1b タイマ (Linux 2.6 以降) は si_overrun と si_timerid を設定する。 si_timerid フィールドはカーネルがタイマを特定するのに使用する内部 ID であり、 timer_create(2) が返すタイマ ID と同じではない。
- SIGCHLD は si_status, si_utime, si_stime を設定する。
- si_int と si_ptr は POSIX.1b シグナルの送信者によって指定される。 詳細は sigqueue(2) を参照のこと。
- SIGILL, SIGFPE, SIGSEGV, SIGBUS は si_addr にエラーが発生したアドレスを設定する。 SIGPOLL は si_band と si_fd を設定する。
si_code は、そのシグナルが送信された理由を示す値である (ビットマスクではない)。 以下のリストに、どのシグナルの場合でも si_code に入りうる値を、シグナルが生成された理由とともに記載する。
- SI_USER
- kill(2) または raise(3)
- SI_KERNEL
- カーネルにより送信された
- SI_QUEUE
- sigqueue(2)
- SI_TIMER
- POSIX タイマが満了した
- SI_MESGQ
- POSIX メッセージキューの状態が変化した (Linux 2.6.6 以降)。 mq_notify(3)参照。
- SI_ASYNCIO
- 非同期 IO (AIO) が完了した
- SI_SIGIO
- キューイングされた SIGIO
- SI_TKILL
- tkill(2) または tgkill(2) (Linux 2.4.19 以降)
SIGILL シグナルの場合、 si_code には以下の値を指定できる:
- ILL_ILLOPC
- 不正な命令コード (opcode)
- ILL_ILLOPN
- 不正なオペランド
- ILL_ILLADR
- 不正なアドレッシングモード
- ILL_ILLTRP
- 不正なトラップ
- ILL_PRVOPC
- 特権が必要な命令コード (opcode)
- ILL_PRVREG
- 特権が必要なレジスタ
- ILL_COPROC
- コプロセッサのエラー
- ILL_BADSTK
- 内部スタックエラー
SIGFPE シグナルの場合、 si_code には以下の値を指定できる:
- FPE_INTDIV
- 整数の 0 による除算
- FPE_INTOVF
- 整数のオーバーフロー
- FPE_FLTDIV
- 浮動小数点の 0 による除算
- FPE_FLTOVF
- 浮動小数点のオーバーフロー
- FPE_FLTUND
- 浮動小数点のアンダーフロー
- FPE_FLTRES
- 浮動小数点の不正確な演算結果 (inexact result)
- FPE_FLTINV
- 浮動小数点の不正な操作
- FPE_FLTSUB
- 範囲外の添字 (subscript)
SIGSEGV シグナルの場合、 si_code には以下の値を指定できる:
- SEGV_MAPERR
- オブジェクトにマッピングされていないアドレス
- SEGV_ACCERR
- マッピングされたオブジェクトに対するアクセス許可がない
SIGBUS シグナルの場合、 si_code には以下の値を指定できる:
- BUS_ADRALN
- 不正なアドレス・アライメント (alignment)
- BUS_ADRERR
- 存在しない物理アドレス
- BUS_OBJERR
- オブジェクト固有のハードウェアエラー
SIGTRAP シグナルの場合、 si_code には以下の値を指定できる:
- TRAP_BRKPT
- プロセスのブレークポイント
- TRAP_TRACE
- プロセスのトレース・トラップ
SIGCHLD シグナルの場合、 si_code には以下の値を指定できる:
- CLD_EXITED
- 子プロセスが終了した (exited)
- CLD_KILLED
- 子プロセスが kill された
- CLD_DUMPED
- 子プロセスが異常終了した
- CLD_TRAPPED
- トレース対象の子プロセスがトラップを上げた
- CLD_STOPPED
- 子プロセスが停止 (stop) した
- CLD_CONTINUED
- 停止していた子プロセスが再開した (Linux 2.6.9 以降)
SIGPOLL シグナルの場合、 si_code には以下の値を指定できる:
返り値¶
sigaction() は成功すれば 0 を返し、エラーならば -1 を返す。
エラー¶
準拠¶
POSIX.1-2001, SVr4.
注意¶
fork(2) 経由で作成された子プロセスは、親プロセスのシグナルの処理方法の コピーを継承する。 execve(2) の前後で、ハンドラが設定されているシグナルの処理方法はデフォルトにリセットされ、 無視が設定されているシグナルの処理方法は変更されずそのままとなる。
POSIX では、 kill(2) や raise(3) 関数で生成できないシグナル SIGFPE, SIGILL, SIGSEGV を無視 (ignore) した場合、その後の動作は未定義である。 ゼロによる整数割り算の結果は未定義となる。 アーキテクチャーによっては、このとき SIGFPE シグナルが生成される。 (同様に負の最大整数を -1 で割ると SIGFPE が生成されるかもしれない) このシグナルを無視すると無限ループに陥るかもしれない。
POSIX.1-1990 では SIGCHLD に SIG_IGN を設定することを認めていない。 POSIX.1-2001 では認められており、 SIGCHLD を無視することでゾンビプロセスの生成を防止することができる (wait(2) を参照)。 さらに、BSD と SystemV では SIGCHLD を無視した際の動作が異なっている。 そのため、完全に移植性がある方法で、終了した子プロセスがゾンビにならないこと を保証するには、 SIGCHLD シグナルを補足し、 wait(2) などを実行するしかない。
POSIX.1-1990 の仕様では SA_NOCLDSTOP のみが定義されている。 POSIX.1-2001 では SA_NOCLDWAIT, SA_RESETHAND, SA_NODEFER, SA_SIGINFO が追加された。 Unix の古い実装で動かすアプリケーションで、 他の sa_flags フラグを使用すると移植性が下がる。
SA_RESETHAND フラグは SVr4 の同じ名前のフラグと互換性がある。
SA_NODEFER フラグは 1.3.9 以降のカーネルでは同じ名前の SVr4 のフラグと互換性がある。 ぞれ以前の Linux カーネルの実装では、このフラグを設定しているシグナル だけでなく、どのシグナルでも受けることを許していた (実際には sa_mask の設定により無効にできる)。
sigaction() の二番目の引き数に NULL を指定して呼び出すと、現在のシグナルハンドラを確認する ことができる。また、二番目と三番目の引き数を NULL にて呼び出すことで、 指定されたシグナルが現在のマシンで使えるかどうかチェックできる。
SIGKILL や SIGSTOP を (sa_mask に指定して) 禁止することはできない。 禁止しようとしても黙って無視される。
シグナル集合の操作に関する詳細は sigsetops(3) を参照すること。
シグナルハンドラ内から安全に呼び出すことができる、 async-signal-safe functions (非同期シングルで安全な関数) の リストについては signal(7) を参照。
非公式¶
SA_SIGINFO が導入される前は、 struct sigcontext 型の二番目の引き数と一緒に sa_handler を使用することで、 いくつかの追加の情報を入手することができた。 詳細についてはカーネルソースの関連部分を見てほしい。 現在はこの使用法は廃止されている。
バグ¶
2.6.13 以前のカーネルでは、 sa_flags に SA_NODEFER を指定した場合、 ハンドラが実行中に配送されたシグナル自身がマスクされなくなるだけでなく、 sa_mask に指定されたシグナルもマスクされなくなる。 このバグは、カーネル 2.6.14 で修正された。
例¶
mprotect(2) 参照。
関連項目¶
kill(1), kill(2), killpg(2), pause(2), sigaltstack(2), signal(2), signalfd(2), sigpending(2), sigprocmask(2), sigqueue(2), sigsuspend(2), wait(2), raise(3), siginterrupt(3), sigsetops(3), sigvec(3), core(5), signal(7)
2008-10-17 | Linux |